/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package xml;

import java.io.File;
import java.io.IOException;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 *
 * @author bi
 */
public class XMLController {

    private Document document;
    private File file;
    private String filename;
    public String[][] table;
    public String[] columnName;

    public XMLController(String filename) {
        try {
            this.filename = filename;
            //Read the document
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            file = new File("xml/" + filename + ".xml");
            document = db.parse(file);


            parseTable();
        } catch (SAXException ex) {
            Logger.getLogger(XMLController.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(XMLController.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ParserConfigurationException ex) {
            Logger.getLogger(XMLController.class.getName()).log(Level.SEVERE, null, ex);
        } catch (Exception ex) {
            Logger.getLogger(XMLController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * Search for specific data that contain value in a record.
     * @param fieldName: The field name the value is in.
     * @param searchValue: The value to search.
     * @return: record index, -1 if not founded.
     */
    public int searchData(String fieldName, String searchValue) {
        for (int i = 0; i < columnName.length; i++) {
            if (columnName[i].equals(fieldName)) {
                return searchData(i, searchValue);
            }
        }
        return -1;
    }

    /**
     * Search for specific data that contain value in a record.
     * @param fieldIndex: The field index the value is in.
     * @param searchValue: The value to search.
     * @return: record index, -1 if not founded.
     */
    public int searchData(int fieldIndex, String searchValue) {
        for (int i = 0; i < table.length; i++) {
            if (table[i][fieldIndex].equals(searchValue)) {
                return i;
            }
        }
        return -1;
    }

    /**
     * Parse Table Function
     *
     * Parse the whole document into table, in-class only
     */
    private void parseTable() {
        //Set the whole document into table
        Node parent = document.getLastChild();
        NodeList listRecord = parent.getChildNodes();
        boolean calcSize = false;
        int rowSize = 0;
        int columnSize = 0;

        Vector<String> vTable = new Vector<String>();
        Vector<String> vColumn = new Vector<String>();

        for (int i = 0; i < listRecord.getLength(); i++) {
            if (listRecord.item(i).getNodeType() != Node.TEXT_NODE) {
                rowSize++;
                NodeList listField = listRecord.item(i).getChildNodes();
                for (int j = 0; j < listField.getLength(); j++) {
                    if (listField.item(j).getNodeType() != Node.TEXT_NODE) {
                        vTable.add(listField.item(j).getFirstChild().getNodeValue());

                        if (vColumn.isEmpty()) {
                            calcSize = true;
                        }
                        if (calcSize) {
                            vColumn.add(listField.item(j).getNodeName());
                        }
                    }
                }
                if (calcSize) {
                    calcSize = false;
                }
            }
        }
        columnSize = vColumn.size();

        table = new String[rowSize][columnSize];
        columnName = new String[columnSize];


        int r = 0;
        int c = 0;
        for (int i = 0; i < vTable.size(); i++) {
            table[r][c] = vTable.get(i);

            if (r == 0) {
                columnName[c] = vColumn.get(i);
            }

            if (c < columnSize - 1) {
                c++;
            } else if (r < rowSize - 1) {
                r++;
                c = 0;
            }
        }
    }

    private void writeTable() {
        Node newTree = document.createElement(filename);
        String newRecordName = filename.substring(0, filename.length() - 1);
        for (int i = 0; i < table.length; i++) {
            Node newRecord = document.createElement(newRecordName);
            for (int j = 0; j < table[i].length; j++) {
                Node newField = document.createElement(columnName[j]);
                Node newValue = document.createTextNode(table[i][j]);
                newField.appendChild(newValue);
                newRecord.appendChild(newField);
            }
            newTree.appendChild(newRecord);
        }
        //Remove everything
        Node parent = document.getLastChild();
        document.removeChild(parent);
        document.appendChild(newTree);

    }

    public void writeXML() {
        try {
            writeTable();

            Source source = new DOMSource(document);
            Result result = new StreamResult(file);
            TransformerFactory tff = TransformerFactory.newInstance();
            Transformer tf = tff.newTransformer();
            tf.transform(source, result);
        } catch (TransformerException ex) {
            Logger.getLogger(XMLController.class.getName()).log(Level.SEVERE, null, ex);
        }

    }
}
